'''
作业：
实现学生管理系统：

学生信息包含：
    - 编号（sid), 姓名（name), 年龄（age), 性别（gender) 四个信息
    - 用面向对象来实现
    - 所有的学生数据保存在文件中

1. 实现菜单函数，输出下列信息，返回用户输入的编号，并进行输入校验。
2. 实现控制函数，用来控制菜单的输出与功能的选择，直到用户选择8，结束程序运行。
3. 实现添加学生函数，函数参数为编号，姓名，年龄，性别四个参数，返回是否添加成功的结果，要求编号不可重复。
4. 实现修改函数，参数为学号，如果学生存在，则进行修改，不存在输出提示，并返回是否修改成功
5. 实现删除函数，参数为学号，如果学生存在，则进行删除，不存在输出提示，并返回是否删除成功
6. 实现删除函数，参数为姓名，如果学生存在，则进行删除（同名学生全部删除），不存在输出提示，并返回是否删除成功
7. 实现查询函数，参数为学号，如果学生存在，则输出学生信息，不存在输出提示，并返回是否查询成功
8. 实现查询函数，参数为姓名，如果学生存在，则输出学生信息（同名学生全部输出），不存在输出提示，并返回是否查询成功
9. 实现函数，输出所有学生信息
'''
import copy
import json

all_students = []
file_path = 'students.txt'
class Students():
    # def __init__(self, sid, name, age, gender):
    #     self.sid = sid
    #     self.name = name
    #     self.age = age
    #     self.gender = gender

    #装饰器：每次查询学号是否存在前都先获取一下所有的学生信息
    def getStudents(fun):
        def inner(self, *args, **kwargs):
            #获取所有信息
            global all_students
            all_students = self.readFile(file_path)
            result = fun(self, *args, **kwargs)
            return result
        return inner

    '''添加学生'''
    def addStudent(self):
        '编号（sid), 姓名（name), 年龄（age), 性别（gender)'
        global all_students
        while True:
            sid = input("请输入学号(输入bye则退出添加)：")
            if sid == 'bye':
                break
            elif self.sid_exists(sid)[0]:
                print("学号已存在!")
            else:
                name = input("请输入姓名：")
                age = input("请输入年龄：")
                gender = input("请输入性别：")
                student = {'sid': sid, 'name': name, 'age': age, 'gender': gender}
                '添加学生到文件'
                result = self.appendFile(file_path, str(student))
                if result:
                    print('添加成功！')
                else:
                    print('添加失败！')

    '''修改学生信息'''
    def modifyStudent(self):
        while True:
            sid = input("请输入学号(输入bye则退出修改)：")
            if sid == 'bye':
                break
            elif self.sid_exists(sid)[0] == False:
                print("学号不存在!")
            else:
                name = input("请输入新姓名：")
                age = input("请输入新年龄：")
                gender = input("请输入新性别：")
                student_new = {'sid': sid, 'name': name, 'age': age, 'gender': gender}
                for i in all_students:
                    if student_new.get("sid") == i.get("sid"):
                        all_students.remove(i)
                        all_students.append(student_new)
                        #重新覆盖写入文件
                        result = self.overwriteFile(file_path, all_students)
                        if result:
                            print('修改成功！', i)
                        else:
                            print('修改失败！')
                        break

    #3. 通过学号删除学生信息
    def deleteBySid(self):
        while True:
            sid = input("请输入学号(输入bye则退出删除)：")
            if sid == 'bye':
                break
            elif self.sid_exists(sid)[0] == False:
                print("学号不存在!")
            else:
                for i in all_students:
                    if sid == i.get("sid"):
                        all_students.remove(i)
                        #重新覆盖写入文件
                        result = self.overwriteFile(file_path, all_students)
                        if result:
                            print('删除成功！', i)
                        else:
                            print('删除失败！')
                        break

    # 4. 通过姓名删除学生信息（同名的都删除）
    def deleteByName(self):
        while True:
            name = input("请输入姓名(输入bye则退出删除)：")
            if name == 'bye':
                break
            elif self.name_exists(name)[0] == False:
                print("学生姓名不存在!")
            else:
                tmp = copy.deepcopy(all_students)
                for i in tmp:
                    if name == i.get("name"):
                        all_students.remove(i)
                 # 重新覆盖写入文件
                result = self.overwriteFile(file_path, all_students)
                if result:
                    print('删除成功！', i)
                else:
                    print('删除失败！')

    #5. 通过学号查询学生信息
    def searchBySid(self):
        while True:
            sid = input("请输入学号(输入bye则退出查询)：")
            if sid == 'bye':
                break
            elif self.sid_exists(sid)[0] == False:
                print("学号不存在!")
            else:
                print(self.sid_exists(sid)[1])

    #6. 通过姓名查询学生信息（同名的都查出来）
    def searchByName(self):
        while True:
            sid = input("请输入学生姓名(输入bye则退出查询)：")
            if sid == 'bye':
                break
            elif self.name_exists(sid)[0] == False:
                print("姓名不存在!")
            else:
                print(self.name_exists(sid)[1])
    #7. 查询所有的学生信息
    def searchAllStudents(self):
        all_students = self.readFile(file_path)
        if len(all_students)>0:
            print("所有学生信息如下:")
            for i in all_students:
                print(i)
        else:
            print("没有任何学生信息数据。")

    '''检查学号是否存在，并返回检查结果，以及学生信息'''
    @getStudents
    def sid_exists(self, sid):
        for i in all_students:
            if i.get('sid') == sid:
                return [True, i]  #存在，且返回学生信息
        return [False, None]  #不存在

    '''检查姓名是否存在，并返回检查结果，以及学生信息'''
    @getStudents
    def name_exists(self, name):
        result = []
        for i in all_students:
            if i.get('name') == name:
                result.append(i)
        if len(result) > 0:
            return [True, result] # 存在，且返回学生信息
        else:
            return [False, None] # 不存在

    def menu(self):
        print("****************************************")
        print("*				学生管理系统			 *")
        print("*  	    1. 添加新学生信息              *")
        print("* 	    2. 通过学号修改学生信息		 *")
        print("*		3. 通过学号删除学生信息		 *")
        print("*		4. 通过姓名删除学生信息		 *")
        print("* 	    5. 通过学号查询学生信息          *")
        print("*		6. 通过姓名查询学生信息          *")
        print("*		7. 显示所有学生信息             *")
        print("*		8. 退出系统			  		 *")
        print("****************************************")

    def run(self):
        while True:
            self.menu()
            select_op = input("请输入菜单数字：")
            if select_op.isdigit():
                select_op = int(select_op)
                if select_op == 1:
                    self.addStudent()
                elif select_op == 2:
                    self.modifyStudent()
                elif select_op == 3:
                    self.deleteBySid()
                elif select_op == 4:
                    self.deleteByName()
                elif select_op == 5:
                    self.searchBySid()
                elif select_op == 6:
                    self.searchByName()
                elif select_op == 7:
                    self.searchAllStudents()
                elif select_op == 8:
                    break
                else:
                    print("请输入有效的菜单数字")
            else:
                print("请输有效的入菜单数字：")

    # 追加写入数据
    def appendFile(self, file_path, data):
        try:
            file = open(file_path, "a")
            # 写入数据
            file.write(data)
            file.write("\n")
        except Exception:
            return False
        else:
            return True
        finally:
            #关闭文件
            file.close()
    #覆盖写入数据
    def overwriteFile(self, file_path, datas):
        try:
            file = open(file_path, "w")
            # 写入数据
            for i in datas:
                # 写入数据
                file.write(str(i))
                file.write("\n")
            # 关闭文件
            file.close()
        except Exception as e:
            print(e)
            return False
        else:
            return True
        finally:
        # 关闭文件
            file.close()

    # 读取数据
    def readFile(self, file_path):
        students = []
        with open(file_path, 'r') as f:
            # 使用循环逐行读取文件内容
            for line in f:
                # student = line.strip() # 输出每一行，使用strip()方法去除行末尾的换行符
                student = line
                to_dict = eval(student) # 将str转为dict
                students.append(to_dict)
            # 或者可以使用 while 循环来一行一行读取文件内容
            # line = f.readline()
            # while line:
            #     print(line.strip())
            #     line = f.readline()
        return students

if __name__ == '__main__':
    stu = Students()
    stu.run()

